package storeSorting

import (
	"context"
	"errors"
	"fmt"
	"github.com/google/uuid"
	"github.com/kuangshp/go-utils/k"
	"github.com/shopspring/decimal"
	"gorm.io/gorm"
	"insighttracking/apps/purchase/auth"
	"insighttracking/common/enum"
	"insighttracking/common/utils"
	"insighttracking/query/dao"
	"insighttracking/query/model"
	"insighttracking/query/service"
	"net/http"

	"insighttracking/apps/purchase/internal/svc"
	"insighttracking/apps/purchase/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
	"os"
)

type CreateStoreSortingApiLogic struct {
	logx.Logger
	ctx     context.Context
	svcCtx  *svc.ServiceContext
	Request *http.Request
}

func NewCreateStoreSortingApiLogic(ctx context.Context, svcCtx *svc.ServiceContext, request *http.Request) *CreateStoreSortingApiLogic {
	hostname, _ := os.Hostname()
	return &CreateStoreSortingApiLogic{
		Logger: logx.WithContext(ctx).WithCallerSkip(0).WithFields(
			logx.Field("Log_UUID", uuid.New().String()),
			logx.Field("hostname", hostname)),
		ctx:     ctx,
		svcCtx:  svcCtx,
		Request: request,
	}
}

func (l *CreateStoreSortingApiLogic) CreateStoreSortingApi(req *types.CreateStoreSortingReq) (resp string, err error) {
	accountInfo, err := auth.GetAccountInfo(l.svcCtx, l.Request)
	if err != nil {
		return "", err
	}
	ordersEntities, err := service.OrdersService.GetByIdListApi(l.ctx, accountInfo.EnterpriseId, req.OrdersIDList)
	if err != nil || len(ordersEntities) == 0 {
		return "", errors.New("传递的订单号错误")
	}
	detailEntities, err := service.OrdersDetailService.GetByOrderIdListApi(l.ctx, req.OrdersIDList)
	if err != nil || len(detailEntities) == 0 {
		return "", errors.New("传递的订单号错误")
	}
	detailMap := k.ToMap(detailEntities, func(item *model.OrdersDetailEntity) (int64, *model.OrdersDetailEntity) {
		return item.ID, item
	})
	var totalAmount = decimal.Zero
	var totalCount = decimal.Zero
	for _, item := range detailEntities {
		outboundCount := item.SpuCount
		totalCount = totalCount.Add(outboundCount)
		spuItem := detailMap[item.ID]
		totalAmount = totalAmount.Add(spuItem.SnapshotPrice.Mul(outboundCount))
	}
	tx := dao.Use(l.svcCtx.MysqlDb).Begin()
	for _, ordersId := range req.OrdersIDList {
		storeSortingEntity, err := service.StoreSortingService.GetStoreSortingByOrderIdApi(l.ctx, ordersId)

		var storeSortingID int64
		ordersEntity, err1 := service.OrdersService.GetByIdApi(l.ctx, ordersId)
		if err1 != nil {
			return "", errors.New("传递的订单号错误")
		}
		if errors.Is(err, gorm.ErrRecordNotFound) {
			storeSortingData := &model.StoreSortingEntity{
				OrderNo:      utils.GenerateTodayOrderNo(l.svcCtx.RedisDb, "FJCK"), // 订单流水号
				EnterpriseID: accountInfo.EnterpriseId,                             // 关联到enterprise表主键id
				CustomerID:   ordersEntity.CustomerID,                              // 客户id,关联到enterprise_customer表主键id
				TotalAmount:  totalAmount,                                          // 订单金额
				TotalCount:   totalCount,                                           // 订单商品数量
				WarehouseID:  ordersEntity.WarehouseID,                             // 出库仓库,关联到warehouse表主键id
				OrdersID:     ordersId,                                             // 关联到订单表id,orders表主键id
				OperateName:  accountInfo.PersonName,                               // 制单员
				OperateID:    accountInfo.PersonId,                                 // 制单员id,关联到员工表
			}
			if err = service.StoreSortingService.CreateApi(l.ctx, tx, storeSortingData); err != nil {
				if err = tx.Rollback(); err != nil {
					return "", err
				}
				return "", err
			}
			storeSortingID = storeSortingData.ID
		} else {
			storeSortingID = storeSortingEntity.ID
			if err = service.StoreSortingService.ModifyByIdApi(l.ctx, tx, storeSortingEntity.ID, storeSortingEntity.TotalCount.Add(totalCount), storeSortingEntity.TotalAmount.Add(totalAmount)); err != nil {
				if err := tx.Rollback(); err != nil {
					return "", err
				}
				return "", err
			}
		}

		// 创建明细
		var storeSortingDetail = make([]*model.StoreSortingDetailEntity, 0)
		entities, err := service.OrdersDetailService.GetByOrderIdListApi(l.ctx, []int64{ordersId})
		if err == nil && len(entities) > 0 {
			for _, item := range entities {
				spuItem, isOk := detailMap[item.ID]
				if !isOk {
					continue
				}
				outboundCount := item.SpuCount
				lossCount := outboundCount.Mul(spuItem.SnapshotLossRate)
				// 判断库存是否足够
				spuInventory := service.SpuInventoryService.GetSpuInventoryApi(l.ctx, accountInfo.EnterpriseId, spuItem.SpuID, ordersEntity.WarehouseID)
				if spuInventory.LessThan(outboundCount.Add(lossCount)) {
					if err = tx.Rollback(); err != nil {
						return "", err
					}
					return "", errors.New("当前商品库存数量少于出库数量,无法出库")
				}
				storeSortingDetail = append(storeSortingDetail, &model.StoreSortingDetailEntity{
					StoreSortingID:          storeSortingID,                  // 分拣单store_sorting主键id
					OrdersDetailID:          item.ID,                         // 主键id
					SpuID:                   spuItem.SpuID,                   // 商品,关联到spu表主键id
					SnapshotSpuName:         spuItem.SnapshotName,            // 快照商品名称
					SnapshotProductImageURL: spuItem.SnapshotProductImageURL, // 快照产品图片
					SnapshotSpuType:         spuItem.SnapshotSpuType,         // 快照商品类型,0表示基础商品,1表示加工商品
					SnapshotUnit:            spuItem.SnapshotUnit,            // 快照单位
					SnapshotCategoryID:      spuItem.SnapshotCategoryID,      // 快照分类id
					SnapshotCategory:        spuItem.SnapshotCategory,        // 快照分类
					LossRate:                spuItem.SnapshotLossRate,        // 快照损耗率
					OrdersCount:             spuItem.SpuCount,                // 下单数量
					SnapshotPrice:           spuItem.SnapshotPrice,           // 快照商品单价
					OutboundCount:           outboundCount,                   // 出库数量
					LossCount:               lossCount,                       // 出库损耗
					OperateName:             accountInfo.PersonName,          // 出库员
					OperateID:               accountInfo.PersonId,            // 出库员id,关联到员工表
					Remark:                  item.Remark,                     // 备注
					UUID:                    utils.UuIdV4(),
				})
			}
			if err = service.StoreSortingDetailService.CreateBatchApi(l.ctx, tx, storeSortingDetail); err != nil {
				if err = tx.Rollback(); err != nil {
					return "", err
				}
				return "", err
			}
			// 修改订单详情状态
			ordersDetailIdList := k.Map(entities, func(item *model.OrdersDetailEntity, index int) int64 {
				return item.ID
			})
			if err = service.OrdersDetailService.ModifyStatusByIdListApi(l.ctx, tx, ordersDetailIdList, enum.OrdersSortingFinishEnum); err != nil {
				return "", err
			}

			func(tx *dao.QueryTx) {
				err := tx.Commit()
				if err != nil {
					fmt.Println(err, "错误了11")
				}
			}(tx)
			ordersDetailEntities, err := service.OrdersDetailService.GetByOrderIdListApi(l.ctx, []int64{ordersId})
			if err == nil && len(ordersDetailEntities) > 0 {
				if k.Every(ordersDetailEntities, func(item *model.OrdersDetailEntity, index int) bool {
					return item.Status == enum.OrdersSortingFinishEnum
				}) {
					// 等全部订单详情都分拣完成订单才改分拣
					if err = service.OrdersService.ModifyStatusByIdApi(l.ctx, nil, []int64{ordersId}, enum.OrdersSortingFinishEnum); err != nil {
						l.Errorf("修改状态失败:[%v]", err)
					}
				} else if err = service.OrdersService.ModifyStatusByIdApi(l.ctx, nil, []int64{ordersId}, enum.OrdersSortingProgressEnum); err != nil {
					l.Errorf("修改状态失败:[%v]", err)
				}
			}
		}

	}
	// 修改订单状态
	return "操作成功", nil
}
